﻿using Kinlo.Entitys;
using Kinlo.MESDocking;
using NewLife;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UIWindows.Domains;
using UIWindows.Enums;
using UIWindows.GlobalStatics;
using UIWindows.Tools.Helper;
using XingLucifer.Devices;
using XingLucifer.IBase.Enums;
using XingLucifer.IBase.Models.PLCInteraktion;

namespace UIWindows.Services.Handle
{
    [Attributes.TaskClass(TaskTypes.多码_前扫码)]
    public class MultiCodeBeforeScanCode : ServierBase
    {
        #region Synchronize
        private volatile int _lock = 0;
        protected void Locked()
        {
            int lockNumber = 0;
            while (Interlocked.Exchange(ref _lock, 1) != 0)
            {
                _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0; _ = 0;
                if (++lockNumber > 50)
                {
                    Thread.Sleep(1);
                    lockNumber = 0;
                }
            }
        }

        protected void UnLock() => Interlocked.Exchange(ref _lock, 0);
        #endregion
        private SnowflakeManager _snowflake;
        private IMESInteraction _interactionWorkOrders;
        public MultiCodeBeforeScanCode(DeviceConfigStatic deviceConfig, SystemConfigStatic systemConfig,
            UserConfigStatic userConfig, ParameterStatic parameterStatic, TemporaryStatic temporaryStatic, HomeStatic homeStatic, MesParameterStatic mesParameterStatic)
            : base(deviceConfig, systemConfig, userConfig, parameterStatic, temporaryStatic, homeStatic, mesParameterStatic)
        {
            _snowflake = new SnowflakeManager(12);
            _interaction = new PreventionCheckInterface(DialogLogHelper.MesLog, DialogLogHelper.MESDialog);
            _interactionWorkOrders = new GetByProductCodeInterface(DialogLogHelper.MesLog, DialogLogHelper.MESDialog);
        }

        public override Task Handle(Context.DataContext context)
        {
            if (!ClearSignal(context)) { return Task.CompletedTask; }
            try
            {
                var plc = _deviceConfig.DeviceList.FirstOrDefault(x => x.ServiceName == context.ServiceName && x.TaskType == TaskTypes.扫描信号).Communication as OmronCIP;
                var device = _deviceConfig.DeviceList.FirstOrDefault(x => x.ServiceName == context.ServiceName && x.TaskType == context.TaskType && x.Index == context.DeviceIndex && x.DeviceType == context.DeviceType);
                DateTime dateTime = DateTime.Now;
                var codes = new List<string>();
                if (_parameterStatic.DecideParameter.EnableEmptyRun || _parameterStatic.DecideParameter.EnablePseudoCode || device == null)
                {
                    for (int i = 0; i < context.Struct_Length; i++)
                    {
                        codes.Add($"Empty{Guid.NewGuid().ToString().Substring(0, 5)}1234567890{new Random().Next(1, 9999):D4}");
                    }
                    if (device == null)
                    {
                        RunLog($"-[{context.DeviceIndex}] 触发设备位置找不到，请注意!!!", MessageLevelType.错误);
                    }
                }
                else
                {
                    var barcode = ScanCode(_parameterStatic.RunParameter.Retries_Count_ScanCode, device.Communication, context.DeviceIndex, barcodeNumber: context.Struct_Length);
                    codes = barcode.Split('_').ToList();
                }

                for (int i = 0; i < context.Struct_Length; i++)
                {
                    ResultTypes resultTypes = ResultTypes.合格;
                    long snowflake = _snowflake.NextId();
                    if (codes[i] == "ERROR")
                    {
                        RunLog($"-[{context.DeviceIndex}] 第{i + 1}个条码扫码失败", MessageLevelType.信息);
                        _homeStatic.ChartData.NG_ScanCode += 1;
                        resultTypes = ResultTypes.扫码失败;
                    }
                    else
                    {
                        _homeStatic.ChartData.Total_Inbound += 1;
                        ProductionData.Meta.TableName = $"ProductionData_{DateTime.Now:yyyy}{DateTime.Now.GetQuarterly()}";
                        var entity = new ProductionData()
                        {
                            SnowflakeId = snowflake,
                            BarCode = codes[i],
                            TimeScanCodeBefore = dateTime.GetJSTimeUtc(),
                            RangeElectrodes = $"{_parameterStatic.RangeParameter.ElectrodesDown}={_parameterStatic.RangeParameter.ElectrodesUP}",
                            RangeAfterWeighing = $"{_parameterStatic.RangeParameter.WeighAfterDown}-{_parameterStatic.RangeParameter.WeighAfterUp}",
                            RangeForeweigh = $"{_parameterStatic.RangeParameter.WeighBeforeDown}-{_parameterStatic.RangeParameter.WeighBeforeUp}",
                            RangeFluidRate = $"{_parameterStatic.RangeParameter.QuantitativeDown}-{_parameterStatic.RangeParameter.Quantitative}-{_parameterStatic.RangeParameter.QuantitativeUp}",
                            BatchElectrolyte = _parameterStatic.CollectionItemsParameter.BatchElectrolyte,
                            ProductType = _parameterStatic.CollectionItemsParameter.ProductType.ToString(),
                            GlueNailBatch = _parameterStatic.CollectionItemsParameter.GlueNailBatch,
                            EquipNum = _parameterStatic.CollectionItemsParameter.EquipNum,
                            ProductionLineNo = _parameterStatic.CollectionItemsParameter.ProductionLineNo,
                            Operator = _temporaryStatic.Mes_Account,
                            ResultTotal = ResultTypes._,
                            ResultScanCodeBefore = ResultTypes.合格,
                            LocationScanCodeBefore = (byte)context.DeviceIndex,
                            WorkOrderNumber = _parameterStatic.CollectionItemsParameter.WorkOrder
                            //CollectionMethod = _parameterStatic.DecideParameter.EnableVariableInjection ? "变量注液" : "定量注液",
                            //ProductionMethod = _parameterStatic.DecideParameter.EnableReinvestmentMode ? "正常" : "复投",
                        };
                        //二注取从其它设备取 电池干重及一注下料重量
                        if (_systemConfig.SCM.MainDeviceType == MainDeviceTypeEnum.二次注液 && _systemConfig.SCM.GetOntData == GetOntDataEnum.其它设备获取)
                        {
                            MySqlHelper mySqlHelper = new MySqlHelper(_parameterStatic.MESParameter.OthenDatabaseurl);
                            var oneData = mySqlHelper.GetBatteryByCode(entity.BarCode);
                            if (oneData.status)
                            {
                                if (oneData.netWeight < 10 || oneData.outputWeight < 10)
                                {
                                    resultTypes = ResultTypes.一注数据不在范围;
                                    entity.ResultScanCodeBefore = ResultTypes.一注数据不在范围;
                                    if (entity.ResultTotal == ResultTypes._)
                                        entity.ResultTotal = entity.ResultScanCodeBefore;
                                }
                                else
                                {
                                    var twoInj = _parameterStatic.RangeParameter.Quantitative - (oneData.outputWeight - oneData.netWeight);
                                    if (twoInj > _parameterStatic.RangeParameter.VariablesUp)
                                    {
                                        resultTypes = ResultTypes.变量注液量不在范围;
                                        entity.ResultScanCodeBefore = ResultTypes.变量注液量不在范围;
                                        if (entity.ResultTotal == ResultTypes._)
                                            entity.ResultTotal = entity.ResultScanCodeBefore;
                                    }
                                }
                                entity.NetWeight = oneData.netWeight;
                                entity.OneAfterWeighing = oneData.outputWeight;
                            }
                            else
                            {
                                resultTypes= ResultTypes.取一注数据失败;
                                entity.ResultScanCodeBefore = ResultTypes.取一注数据失败;
                                if (entity.ResultTotal == ResultTypes._)
                                    entity.ResultTotal = entity.ResultScanCodeBefore;
                            }
                        }

                        for (int k = 0; k < 3; k++)
                        {
                            try
                            {
                                RunLog("开始插入数据库");
                                entity.Insert();
                                Locked();
                                entity.Items.Add("TableName", ProductionData.Meta.TableName);
                                _temporaryStatic.EntityCache.Insert(0, entity);
                                if (_temporaryStatic.EntityCache.Count > 600)
                                {
                                    _temporaryStatic.EntityCache.RemoveAt(599);
                                }
                                UnLock();
                                RunLog($"-[{context.DeviceIndex}] ID:[{snowflake}]对应的条码为:[{codes[i]}] 插入数据库成功");
                                break;
                            }
                            catch (Exception ex)
                            {
                                RunLog($"-[{context.DeviceIndex}] ID:[{snowflake}]对应的条码为:[{codes[i]}] 第[{k}]次 保存数据库失败：{ex}");
                                if (k == 2) { resultTypes = ResultTypes.扫码NG; }
                                Thread.Sleep(500);
                            }
                        }


                        #region 进站及工单接口
                        if (_parameterStatic.DecideParameter.EnableMES && _parameterStatic.DecideParameter.EnablePreventionCheck && resultTypes == ResultTypes.合格)
                        {
                            resultTypes = BatteryInputDataUpload(_interaction, _interactionWorkOrders, entity);

                        }
                        #endregion
                    }
                    for (int k = 0; k < 3; k++)
                    {
                        RunLog($"{context.Address_Struct}[{i}].Code 标签!!!");
                        if (plc.WriteSingle(codes[i], $"{context.Address_Struct}[{i}].Code"))
                        {
                            RunLog($"-[{context.DeviceIndex}] 条码:[{codes[i]}] 写入成功!!!");
                            break;
                        }
                        RunLog($"-[{context.DeviceIndex}] 条码:[{codes[i]}] 写入失败 第[{k}]次");
                    }
                    BatteryModel model = new BatteryModel();
                    model.ID = snowflake;
                    model.Results_PC = (short)(resultTypes == ResultTypes.合格 ? 1 : (resultTypes != ResultTypes.MES_NG ? 2 : 3));
                    for (int k = 0; k < 3; k++)
                    {
                        if (plc.WriteClass(model, $"{context.Address_Struct}[{i}].face", 35167))
                        {
                            RunLog($"-[{context.DeviceIndex}] ID:[{model.ID}] 结果:[{model.Results_PC}] 写入成功!!!");
                            break;
                        }
                        RunLog($"-[{context.DeviceIndex}] ID:[{model.ID}] 结果:[{model.Results_PC}] 写入失败 第[{k}]次");
                    }
                    _homeStatic.AddInBattery(codes[i], resultTypes, dateTime, i + 1);
                }
            }
            catch (Exception ex)
            {
                RunLog($"异常：{ex}", MessageLevelType.错误);
            }
            return base.Handle(context);
        }
    }
}
